package com.tongtong.middleware.blockchain.controller;

import com.tongtong.middleware.blockchain.client.web3j.WEB3JService;
import com.tongtong.middleware.blockchain.entity.TblUserChainAccountEntity;
import com.tongtong.middleware.blockchain.service.TblUserChainAccountService;
import com.tongtong.middleware.util.avatar.Avatar;
import com.tongtong.middleware.vo.params.AccountParams;
import com.tongtong.middleware.vo.response.AccountResponse;
import com.tongtong.middleware.vo.response.EstimateGasRes;
import com.tongtong.middleware.vo.response.TransactionMergeData;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.core.methods.response.EthBlock;
import org.web3j.utils.Numeric;
import xyz.xtt.common.response.ApiResult;

import java.io.IOException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.Objects;
import java.util.UUID;

@RestController
@RequestMapping("/eth")
@Slf4j
public class ETHController {
	@Autowired
	WEB3JService web3jService;
	@Autowired
	TblUserChainAccountService tblUserChainAccountService;

	/**
	 * 创建/查询账户
	 */
	@PostMapping("/account")
	public ApiResult<AccountResponse> createAccount(@Valid @RequestBody AccountParams request, BindingResult bindingResult) {
		if (bindingResult.hasErrors()) {
			return ApiResult.build(9527, Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage());
		}
		// 先查询数据库是否存在，如果不存在则生成并更新
		TblUserChainAccountEntity tblUserChainAccountEntity = tblUserChainAccountService.findByAppUserId(request.getUserId());
		if (tblUserChainAccountEntity == null) {
			log.error("【失败】/eth/account: AppUserId => {} err => {}", request.getUserId(), "用户不存在～～！！");
			return ApiResult.build(9527, "用户不存在");
		}
		// 组装返回内容
		AccountResponse resData = new AccountResponse();
		if (tblUserChainAccountEntity.getChainAccount().length() == 42) {
			resData.setAddress(tblUserChainAccountEntity.getChainAccount());
			resData.setAvatar(Avatar.generate(request.getUserId()));
			return ApiResult.ok(resData);
		}

		// 私钥计算方式：组成用户名+"eth-666"+随机数进行SHA3-256
		String address = null;
		String avatar = null;
		try {
			UUID uuid = UUID.randomUUID();
			String uuidString = uuid.toString();
			String uuidWithoutDashes = uuidString.replaceAll("-", "");
			String data = request.getUserId() + "eth-666" + uuidWithoutDashes;
			MessageDigest digest = MessageDigest.getInstance("SHA3-256");
			byte[] hash = digest.digest(data.getBytes());

			// 将私钥字节数组转换为十六进制字符串
			String privateKey = Numeric.toHexStringNoPrefix(hash);

			// 根据私钥生成以太坊地址
			Credentials credentials = Credentials.create(privateKey);
			address = credentials.getAddress();

			log.info("【成功】User ID: {} Address: {}", request.getUserId(), address);
			// 使用用户ID生成头像
			avatar = Avatar.generate(request.getUserId());
			tblUserChainAccountService.UpdateByAppUserId(request.getUserId(), address, uuidWithoutDashes);
		} catch (Exception e) {
			log.error("【失败】createAccount:Exception=>{}", e.getMessage());
		}

		resData.setAddress(address);
		resData.setAvatar(avatar);
		return ApiResult.ok(resData);
	}

	@GetMapping("/getBlockNumber")
	public ApiResult<BigInteger> getBlockNumber() {
        BigInteger blockNumber;
        try {
            blockNumber = web3jService.blockNumber();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return ApiResult.ok(blockNumber);
    }
	/**
	 * 根据交易hash获取交易全部信息
	 */
	@GetMapping("/getTransactionInfo")
	public ApiResult<TransactionMergeData> getTransactionInfo(@RequestParam("hash") String hash) {
		if (hash == null || hash.length() != 66) {
			return ApiResult.build(9527, "hash is illegal", null);
		}
		TransactionMergeData transactionMergeData;
		try {
			transactionMergeData = web3jService.getTransactionInfo(hash);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
		return ApiResult.ok(transactionMergeData);
	}

	/**
	 * 根据区块高度获取区块信息
	 */
	@GetMapping("/getBlockByNumber")
	public ApiResult<EthBlock.Block> getBlockByNumber(@RequestParam("blockNumber") BigInteger blockNumber) {
		if (blockNumber.compareTo(BigInteger.ONE) < 0) {
			return ApiResult.build(9527, "blockNumber is illegal", null);
		}
		EthBlock ethBlock;
		try {
			ethBlock = web3jService.getBlockByNumber(blockNumber);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
		return ApiResult.ok(ethBlock.getResult());
	}

	/**
	 * 获取指定账户的能量值
	 */
	@GetMapping("/getBalance")
	public ApiResult<BigInteger> getBalance(@RequestParam("account") String account) {
		if (account.length() != 42) {
			return ApiResult.build(9527, "account is illegal", null);
		}
		BigInteger balance;
		try {
			balance = web3jService.getBalance(account);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
		return ApiResult.ok(balance);
	}

	@GetMapping("/estimateGas")
	public ApiResult<EstimateGasRes> estimateGas(@RequestParam("from") String from, @RequestParam("to") String to, @RequestParam("input") String input) {
		EstimateGasRes res;
		try {
			// 查询合约，随便用个地址就行
			res = web3jService.estimateGas(from, to, input);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
		return ApiResult.ok(res);
	}
}
